local Button = require('src/Entities/Button')
local Color = require('libs/colorlibrary/colorlibrary')
local Entity = require('src/Entities/Entity')
local Graphics = require('src/graphics')
local i18n = require('libs/i18n')
local IsoMap = require('libs/isomap/isomap')
local Label = require('src/Entities/Label')
local Log = require('src/Log')
local Picture = require('src/Widgets/Picture')
local Snow = require('libs/love-snowflakes/snow')
local State = require('src/State')
local TiledLoader = require('libs/tiledloader/tiledloader')
local Tween = require('libs/tween/tween')

-- TODO переместить в snow!
local snowTimer = 0

local tiledMapState = State:derive('TiledMapState')

-- TODO переоформить это?
--tiledMapState.music = 'music/preciouswasteland.ogg'

-- state --
function tiledMapState:load()
    self.screenWidth = love.graphics.getWidth()
    self.screenHeight = love.graphics.getHeight()
    zoom = 1
    zoomL = 1
    x = 0
    y = 0

    self.IsoMap = IsoMap

    --love.graphics.reset()
    -- fonts
    --     -- TODO переделать на более общий шрифт?
    self.FontWidth = g_fontMedium:getWidth('.')
    self.FontHeight = g_fontMedium:getHeight('.')

    local w, h = love.window.getMode()
    -- snow
    local sw = love.graphics.getWidth()
    local sh = love.graphics.getHeight()
    Snow:load(sw, sh, 3000)

    -- tiles and layers

--local state = ENGINE.SM:getState('locationState')
--ENGINE.SM:dumpStack()

--    self.tiles, self.layers = TiledLoader:Load('test_02.tmx')
    self.tiles, self.layers = TiledLoader:Load(self.map)

    -- loading cursor tile
    self.tiles.cursorTile = love.graphics.newImage('tiles/128x64/tile_cursor.png')
    -- TODO del?
    --IsoMap.cursorLastUpdateTime = love.timer.getTime()
    --self.mouseLastMoveTime = love.timer.getTime()
    self.mouseLastMoveTime = nil
    self.mouseX = nil
    self.mouseY = nil
    self.mousePointerGrid = false
--    self.mousePointerGrid = true

--print(self.layers[2][1][1])
--print(self.layers[2][2][1])
--print(self.layers[2][3][1])

    -- outline shader
    local shader = 'libs/shaders/outline/outline.glsl'
    Log:info('Loading outline shader: '..shader)
    -- TODO move it somewhere
    g_shader = love.graphics.newShader(shader)

    -- player panel
    -- player panel cover
    local ppImage = love.graphics.newImage('images/textures/leather_antique_cover_01.png')
    local ppImagew = ppImage:getWidth()
    local ppImageh = ppImage:getHeight()
    self.playerPanel = Picture(0, sh - ppImageh, sw, nil, ppImage, Color.white, 'center', 'center')

    -- player panel info
    local ppInfoImage = love.graphics.newImage('images/textures/squared_paper_2_a.png')
    local ppInfoImagew = ppInfoImage:getWidth()
    self.playerPanelInfo = Picture(sw - ppInfoImagew, 0, nil, ppImageh, ppInfoImage, Color.white, 'right', 'center', true)
    -- TODO
    -- player panel info label temporary
    local ppLabel = Label(10, 10, ppInfoImagew - 40, nil, i18n.translate('Tmp'), g_fontTypeWriterSmall, Color.black, 'left', 'top')

    -- player panel item
    local ppItemImage = love.graphics.newImage('images/textures/player_panel.png')
    local ppItemImagew = ppItemImage:getWidth()
    self.playerPanelItem = Picture((sw - ppItemImagew)/2, 0, nil, ppImageh, ppItemImage, Color.white, 'right', 'center', true)
    -- TODO
    -- knife
    local ppItemImageTMP = love.graphics.newImage('images/inventory/item_knife_01.png')
    local ppItemImagewTMP = ppItemImageTMP:getWidth()
    local ppItemImagehTMP = ppItemImageTMP:getHeight()
    self.playerPanelItemTMP = Picture((sw - ppItemImagewTMP)/2, sh - ppItemImagehTMP - 30, nil, ppImagehTMP, ppItemImageTMP, Color.white, 'right', 'center', true)

    -- player panel combining
    self.playerPanel:addComponent(self.playerPanelInfo)
    self.playerPanelInfo:addComponent(ppLabel)
    self.playerPanel:addComponent(self.playerPanelItem)

    -- events
    ENGINE.EVENTS:hook('key_pressed', self.keyboard)
    ENGINE.EVENTS:hook('onMouseClick', self.mouseClick)


    -- sounds
    --    self.soundMove = love.audio.newSource('sounds/pick.ogg', 'static')
    --    self.soundAccept = love.audio.newSource('sounds/accept.ogg', 'static')

    -- sounds setup for menu
    --    menuMain:setSndMove(self.soundMove)
    --    menuMain:setSndSuccess(self.soundAccept)
    Log:debug('Memory used (in kB): ' .. math.floor(collectgarbage('count')))
end


function tiledMapState:update(dt)
    tiledMapState.updateMouse(self, dt)
    -- snow update
    --    ENGINE.SM:update(dt)
    snowTimer = snowTimer + dt
    if snowTimer > 0.02 then
        Snow:update(dt)
        snowTimer = 0
    end
    --    menuMain:update()
    --    if ENGINE.EVENTS.events['f10'] then
    --        ENGINE.EVENTS.events['f10'] = nil
    --        -- TODO общий выход
    --        love.event.quit(0)
    --    end
    -- tween
    --    self.cover:update(dt)
    --    self.buttonStartGame:update(dt)
    if love.keyboard.isDown("left") then x = x + 900*dt end
    if love.keyboard.isDown("right") then x = x - 900*dt end
    if love.keyboard.isDown("up") then y = y+900*dt end
    if love.keyboard.isDown("down") then y = y-900*dt end
    zoomL = lerp(zoomL, zoom, 0.05*(dt*300))

    -- player panel
    self.playerPanel:update(dt)

--      local tx, ty = IsoMap:getTileUnderCursor(x, y, zoomL, self.tiles, self.layers)
end

-- TODO move it?
function lerp(a, b, rate) --EMPLOYEE OF THE MONTH
    local result = (1 - rate) * a + rate * b
    return result
end


function tiledMapState:draw()
    -- draw background
    --love.graphics.setBlendMode('alpha', 'premultiplied')
    --love.graphics.setColor(1, 1, 1, 1)
    --    self.bg:draw()
    -- draw project name
    --    self.labelProjectName:draw()
    -- menu draw
    --    self.cover:draw()

--    IsoMap:drawGround(self, x, y, zoomL, self.tiles, self.layers, self.screenWidth, self.screenHeight)
    self.IsoMap:drawGround(self, x, y, zoomL, self.tiles, self.layers, self.screenWidth, self.screenHeight)
    --IsoMap:drawObjects(x, y, zoomL, self.tiles, self.layers)
    love.graphics.setColor(1, 0, 1, 1)
    info = love.graphics.getStats()
--    love.graphics.print("FPS: "..love.timer.getFPS())
    love.graphics.print("Draw calls: "..info.drawcalls, 0, 25)
--    love.graphics.print("Texture memory: "..((info.texturememory/1024)/1024).."mb", 0, 50)
--    love.graphics.print("Zoom level: "..zoom, 0, 75)
--    local state = ENGINE.SM:GetTopState()
    local x = self.IsoMap.tileUnderCursorx
    local y = self.IsoMap.tileUnderCursory
    if x and y then
        love.graphics.print("X: "..math.floor(x).." Y: "..math.floor(y), 0, 100)
    end

    -- draw snow
--    Snow:draw()

    -- draw player panel
    self.playerPanel:draw()
    self.playerPanelItemTMP:draw()

    -- floating label
    if self.objectUnderMouseLabel then
        self.objectUnderMouseLabel:draw()
    end

    Graphics:ShowFPS()
end


function tiledMapState:exit()
    -- events
    ENGINE.EVENTS:unhook('key_pressed', self.keyboard)
    ENGINE.EVENTS:unhook('onMouseClick', self.mouseClick)
end


--function love.keypressed(key, scancode, isrepeat)
--    menuSystem.keypressed(scancode)
--
--    if scancode == 'return' then
--        print('A')
--        love.event.quit()
--    end
--end


--function love.mousemoved(x, y, dx, dy, istouch)
--    menuSystem.mousemoved(x, y)
--end

--function love.mousemoved(x, y, dx, dy, istouch)
function tiledMapState:updateMouse(dt)
    local mx, my = love.mouse.getPosition()
    if not ((self.mouseX == mx) and (self.mouseY == my)) then
        -- mouse moved
        self.mouseX = mx
        self.mouseY = my
        self.mouseLastMoveTime = love.timer.getTime()
        self.objectUnderMouse = nil
        self.objectUnderMousePrevious = nil
        self.objectUnderMouseLabel = nil
    else
        if (love.timer.getTime() > self.mouseLastMoveTime + 1) then
            -- update floating label
            if self.objectUnderMouse then
                if self.objectUnderMousePrevious == self.objectUnderMouse then
                    -- same object as before
                else
                    -- new object
                    self.objectUnderMousePrevious = self.objectUnderMouse
                    self.objectUnderMouseLabel = Label(mx, my - 30, nil, nil, self.objectUnderMouse, g_fontTypeWriterSmall, Color.white, 'left', 'center', Color.black)
                end
            end
        end
    end
--    print(self.mx, self.my)
    -- check for player panel coordinates
--    if (my > tiledMapState.screenHeight - tiledMapState.playerPanel.h) then
--    if (my > self.screenHeight - self.playerPanel.h) then
    if (my > self.screenHeight - 200) then
--        cursor = love.mouse.newCursor('images/cursor/cursor_plain2.png', 0, 0)
        love.mouse.setCursor()
    else
--        cursor = love.mouse.newCursor('images/cursor/cursor_plain2.png', 0, 0)
--        love.mouse.setCursor(cursor)
        ENGINE.MOUSE:resetCursor()
    end
end

function tiledMapState:keyboard()
    if love.keyboard.isDown('escape') then
        local state = ENGINE.SM:GetTopState()
        state:setCursorPlain()
        ENGINE.SM:switch('ExitConfirmState', 'ExitConfirmState', true)
    end
end

function tiledMapState:setCursorPlain()
--    local state = ENGINE.SM:GetTopState()
    local state = self
    state.mousePointerGrid = false
    love.mouse.setVisible(true)
end

function tiledMapState:setCursorGrid()
--    local state = ENGINE.SM:GetTopState()
    local state = self
    state.mousePointerGrid = true
    love.mouse.setVisible(false)
end

function tiledMapState:mouseClick()
    local button = self
    -- secondary click (right mouse button)
    if button == '2' then
        local state = ENGINE.SM:GetTopState()
        if state.mousePointerGrid then
            state:setCursorPlain()
        else
            state:setCursorGrid()
        end
    end
end

-- ----------

-- TODO move it somewhere
function love.wheelmoved(x, y)
    if y > 0 then
        zoom = zoom + 0.1
    elseif y < 0 then
        zoom = zoom - 0.1
    end

    if zoom < 0.1 then
        zoom = 0.1
    end
    if zoom > 5 then
        zoom = 5
    end
end

return tiledMapState
